
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>django.contrib.auth.hashers &#8212; Django 2.2.12.dev20200304094918 documentation</title>
    <link rel="stylesheet" href="../../../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../../../../" src="../../../../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../../../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../../../_static/language_data.js"></script>
    <link rel="index" title="Index" href="../../../../genindex.html" />
    <link rel="search" title="Search" href="../../../../search.html" />



 
<script type="text/javascript" src="../../../../templatebuiltins.js"></script>
<script type="text/javascript">
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../../../../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);</script>

  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../../../index.html">Django 2.2.12.dev20200304094918 documentation</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../../../index.html">Home</a>  |
        <a title="Table of contents" href="../../../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../../../genindex.html">Index</a>  |
        <a title="Module index" href="../../../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    <a href="../../../index.html" title="Module code" accesskey="U">up</a></div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="_modules-django-contrib-auth-hashers">
            
  <h1>Source code for django.contrib.auth.hashers</h1><div class="highlight"><pre>
<span></span><span class="kn">import</span> <span class="nn">base64</span>
<span class="kn">import</span> <span class="nn">binascii</span>
<span class="kn">import</span> <span class="nn">functools</span>
<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">import</span> <span class="nn">importlib</span>
<span class="kn">import</span> <span class="nn">warnings</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="k">import</span> <span class="n">OrderedDict</span>

<span class="kn">from</span> <span class="nn">django.conf</span> <span class="k">import</span> <span class="n">settings</span>
<span class="kn">from</span> <span class="nn">django.core.exceptions</span> <span class="k">import</span> <span class="n">ImproperlyConfigured</span>
<span class="kn">from</span> <span class="nn">django.core.signals</span> <span class="k">import</span> <span class="n">setting_changed</span>
<span class="kn">from</span> <span class="nn">django.dispatch</span> <span class="k">import</span> <span class="n">receiver</span>
<span class="kn">from</span> <span class="nn">django.utils.crypto</span> <span class="k">import</span> <span class="p">(</span>
    <span class="n">constant_time_compare</span><span class="p">,</span> <span class="n">get_random_string</span><span class="p">,</span> <span class="n">pbkdf2</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">django.utils.module_loading</span> <span class="k">import</span> <span class="n">import_string</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="k">import</span> <span class="n">gettext_noop</span> <span class="k">as</span> <span class="n">_</span>

<span class="n">UNUSABLE_PASSWORD_PREFIX</span> <span class="o">=</span> <span class="s1">&#39;!&#39;</span>  <span class="c1"># This will never be a valid encoded hash</span>
<span class="n">UNUSABLE_PASSWORD_SUFFIX_LENGTH</span> <span class="o">=</span> <span class="mi">40</span>  <span class="c1"># number of random chars to add after UNUSABLE_PASSWORD_PREFIX</span>


<div class="viewcode-block" id="is_password_usable"><a class="viewcode-back" href="../../../../topics/auth/passwords.html#django.contrib.auth.hashers.is_password_usable">[docs]</a><span class="k">def</span> <span class="nf">is_password_usable</span><span class="p">(</span><span class="n">encoded</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Return True if this password wasn&#39;t generated by</span>
<span class="sd">    User.set_unusable_password(), i.e. make_password(None).</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="n">encoded</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">UNUSABLE_PASSWORD_PREFIX</span><span class="p">)</span></div>


<div class="viewcode-block" id="check_password"><a class="viewcode-back" href="../../../../topics/auth/passwords.html#django.contrib.auth.hashers.check_password">[docs]</a><span class="k">def</span> <span class="nf">check_password</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">,</span> <span class="n">setter</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">preferred</span><span class="o">=</span><span class="s1">&#39;default&#39;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Return a boolean of whether the raw password matches the three</span>
<span class="sd">    part encoded digest.</span>

<span class="sd">    If setter is specified, it&#39;ll be called when you need to</span>
<span class="sd">    regenerate the password.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">password</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">is_password_usable</span><span class="p">(</span><span class="n">encoded</span><span class="p">):</span>
        <span class="k">return</span> <span class="kc">False</span>

    <span class="n">preferred</span> <span class="o">=</span> <span class="n">get_hasher</span><span class="p">(</span><span class="n">preferred</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">hasher</span> <span class="o">=</span> <span class="n">identify_hasher</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
        <span class="c1"># encoded is gibberish or uses a hasher that&#39;s no longer installed.</span>
        <span class="k">return</span> <span class="kc">False</span>

    <span class="n">hasher_changed</span> <span class="o">=</span> <span class="n">hasher</span><span class="o">.</span><span class="n">algorithm</span> <span class="o">!=</span> <span class="n">preferred</span><span class="o">.</span><span class="n">algorithm</span>
    <span class="n">must_update</span> <span class="o">=</span> <span class="n">hasher_changed</span> <span class="ow">or</span> <span class="n">preferred</span><span class="o">.</span><span class="n">must_update</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span>
    <span class="n">is_correct</span> <span class="o">=</span> <span class="n">hasher</span><span class="o">.</span><span class="n">verify</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">)</span>

    <span class="c1"># If the hasher didn&#39;t change (we don&#39;t protect against enumeration if it</span>
    <span class="c1"># does) and the password should get updated, try to close the timing gap</span>
    <span class="c1"># between the work factor of the current encoded password and the default</span>
    <span class="c1"># work factor.</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">is_correct</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">hasher_changed</span> <span class="ow">and</span> <span class="n">must_update</span><span class="p">:</span>
        <span class="n">hasher</span><span class="o">.</span><span class="n">harden_runtime</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">setter</span> <span class="ow">and</span> <span class="n">is_correct</span> <span class="ow">and</span> <span class="n">must_update</span><span class="p">:</span>
        <span class="n">setter</span><span class="p">(</span><span class="n">password</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">is_correct</span></div>


<div class="viewcode-block" id="make_password"><a class="viewcode-back" href="../../../../topics/auth/passwords.html#django.contrib.auth.hashers.make_password">[docs]</a><span class="k">def</span> <span class="nf">make_password</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">hasher</span><span class="o">=</span><span class="s1">&#39;default&#39;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Turn a plain-text password into a hash for database storage</span>

<span class="sd">    Same as encode() but generate a new random salt. If password is None then</span>
<span class="sd">    return a concatenation of UNUSABLE_PASSWORD_PREFIX and a random string,</span>
<span class="sd">    which disallows logins. Additional random string reduces chances of gaining</span>
<span class="sd">    access to staff or superuser accounts. See ticket #20079 for more info.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">password</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">UNUSABLE_PASSWORD_PREFIX</span> <span class="o">+</span> <span class="n">get_random_string</span><span class="p">(</span><span class="n">UNUSABLE_PASSWORD_SUFFIX_LENGTH</span><span class="p">)</span>
    <span class="n">hasher</span> <span class="o">=</span> <span class="n">get_hasher</span><span class="p">(</span><span class="n">hasher</span><span class="p">)</span>
    <span class="n">salt</span> <span class="o">=</span> <span class="n">salt</span> <span class="ow">or</span> <span class="n">hasher</span><span class="o">.</span><span class="n">salt</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">hasher</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span></div>


<span class="nd">@functools</span><span class="o">.</span><span class="n">lru_cache</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">get_hashers</span><span class="p">():</span>
    <span class="n">hashers</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">hasher_path</span> <span class="ow">in</span> <span class="n">settings</span><span class="o">.</span><span class="n">PASSWORD_HASHERS</span><span class="p">:</span>
        <span class="n">hasher_cls</span> <span class="o">=</span> <span class="n">import_string</span><span class="p">(</span><span class="n">hasher_path</span><span class="p">)</span>
        <span class="n">hasher</span> <span class="o">=</span> <span class="n">hasher_cls</span><span class="p">()</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">hasher</span><span class="p">,</span> <span class="s1">&#39;algorithm&#39;</span><span class="p">):</span>
            <span class="k">raise</span> <span class="n">ImproperlyConfigured</span><span class="p">(</span><span class="s2">&quot;hasher doesn&#39;t specify an &quot;</span>
                                       <span class="s2">&quot;algorithm name: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">hasher_path</span><span class="p">)</span>
        <span class="n">hashers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">hasher</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">hashers</span>


<span class="nd">@functools</span><span class="o">.</span><span class="n">lru_cache</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">get_hashers_by_algorithm</span><span class="p">():</span>
    <span class="k">return</span> <span class="p">{</span><span class="n">hasher</span><span class="o">.</span><span class="n">algorithm</span><span class="p">:</span> <span class="n">hasher</span> <span class="k">for</span> <span class="n">hasher</span> <span class="ow">in</span> <span class="n">get_hashers</span><span class="p">()}</span>


<span class="nd">@receiver</span><span class="p">(</span><span class="n">setting_changed</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">reset_hashers</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;setting&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;PASSWORD_HASHERS&#39;</span><span class="p">:</span>
        <span class="n">get_hashers</span><span class="o">.</span><span class="n">cache_clear</span><span class="p">()</span>
        <span class="n">get_hashers_by_algorithm</span><span class="o">.</span><span class="n">cache_clear</span><span class="p">()</span>


<span class="k">def</span> <span class="nf">get_hasher</span><span class="p">(</span><span class="n">algorithm</span><span class="o">=</span><span class="s1">&#39;default&#39;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Return an instance of a loaded password hasher.</span>

<span class="sd">    If algorithm is &#39;default&#39;, return the default hasher. Lazily import hashers</span>
<span class="sd">    specified in the project&#39;s settings file if needed.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">algorithm</span><span class="p">,</span> <span class="s1">&#39;algorithm&#39;</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">algorithm</span>

    <span class="k">elif</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="s1">&#39;default&#39;</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">get_hashers</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>

    <span class="k">else</span><span class="p">:</span>
        <span class="n">hashers</span> <span class="o">=</span> <span class="n">get_hashers_by_algorithm</span><span class="p">()</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">hashers</span><span class="p">[</span><span class="n">algorithm</span><span class="p">]</span>
        <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Unknown password hashing algorithm &#39;</span><span class="si">%s</span><span class="s2">&#39;. &quot;</span>
                             <span class="s2">&quot;Did you specify it in the PASSWORD_HASHERS &quot;</span>
                             <span class="s2">&quot;setting?&quot;</span> <span class="o">%</span> <span class="n">algorithm</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">identify_hasher</span><span class="p">(</span><span class="n">encoded</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Return an instance of a loaded password hasher.</span>

<span class="sd">    Identify hasher algorithm by examining encoded hash, and call</span>
<span class="sd">    get_hasher() to return hasher. Raise ValueError if</span>
<span class="sd">    algorithm cannot be identified, or if hasher is not loaded.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c1"># Ancient versions of Django created plain MD5 passwords and accepted</span>
    <span class="c1"># MD5 passwords with an empty salt.</span>
    <span class="k">if</span> <span class="p">((</span><span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">32</span> <span class="ow">and</span> <span class="s1">&#39;$&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">encoded</span><span class="p">)</span> <span class="ow">or</span>
            <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">37</span> <span class="ow">and</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;md5$$&#39;</span><span class="p">))):</span>
        <span class="n">algorithm</span> <span class="o">=</span> <span class="s1">&#39;unsalted_md5&#39;</span>
    <span class="c1"># Ancient versions of Django accepted SHA1 passwords with an empty salt.</span>
    <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">46</span> <span class="ow">and</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;sha1$$&#39;</span><span class="p">):</span>
        <span class="n">algorithm</span> <span class="o">=</span> <span class="s1">&#39;unsalted_sha1&#39;</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">algorithm</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">get_hasher</span><span class="p">(</span><span class="n">algorithm</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">6</span><span class="p">,</span> <span class="n">char</span><span class="o">=</span><span class="s2">&quot;*&quot;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Return the given hash, with only the first ``show`` number shown. The</span>
<span class="sd">    rest are masked with ``char`` for security reasons.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">masked</span> <span class="o">=</span> <span class="nb">hash</span><span class="p">[:</span><span class="n">show</span><span class="p">]</span>
    <span class="n">masked</span> <span class="o">+=</span> <span class="n">char</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="nb">hash</span><span class="p">[</span><span class="n">show</span><span class="p">:])</span>
    <span class="k">return</span> <span class="n">masked</span>


<span class="k">class</span> <span class="nc">BasePasswordHasher</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Abstract base class for password hashers</span>

<span class="sd">    When creating your own hasher, you need to override algorithm,</span>
<span class="sd">    verify(), encode() and safe_summary().</span>

<span class="sd">    PasswordHasher objects are immutable.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="kc">None</span>
    <span class="n">library</span> <span class="o">=</span> <span class="kc">None</span>

    <span class="k">def</span> <span class="nf">_load_library</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">library</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">library</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
                <span class="n">name</span><span class="p">,</span> <span class="n">mod_path</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">library</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">mod_path</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">library</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">module</span> <span class="o">=</span> <span class="n">importlib</span><span class="o">.</span><span class="n">import_module</span><span class="p">(</span><span class="n">mod_path</span><span class="p">)</span>
            <span class="k">except</span> <span class="ne">ImportError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Couldn&#39;t load </span><span class="si">%r</span><span class="s2"> algorithm library: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span>
                                 <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span>
            <span class="k">return</span> <span class="n">module</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Hasher </span><span class="si">%r</span><span class="s2"> doesn&#39;t specify a library attribute&quot;</span> <span class="o">%</span>
                         <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Generate a cryptographically secure nonce salt in ASCII.&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">get_random_string</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Check if the given password is correct.&quot;&quot;&quot;</span>
        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">&#39;subclasses of BasePasswordHasher must provide a verify() method&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create an encoded database value.</span>

<span class="sd">        The result is normally formatted as &quot;algorithm$salt$hash&quot; and</span>
<span class="sd">        must be fewer than 128 characters.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">&#39;subclasses of BasePasswordHasher must provide an encode() method&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a summary of safe values.</span>

<span class="sd">        The result is a dictionary and will be used where the password field</span>
<span class="sd">        must be displayed to construct a safe representation of the password.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">&#39;subclasses of BasePasswordHasher must provide a safe_summary() method&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">return</span> <span class="kc">False</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Bridge the runtime gap between the work factor supplied in `encoded`</span>
<span class="sd">        and the work factor suggested by this hasher.</span>

<span class="sd">        Taking PBKDF2 as an example, if `encoded` contains 20000 iterations and</span>
<span class="sd">        `self.iterations` is 30000, this method should run password through</span>
<span class="sd">        another 10000 iterations of PBKDF2. Similar approaches should exist</span>
<span class="sd">        for any hasher that has a work factor. If not, this method should be</span>
<span class="sd">        defined as a no-op to silence the warning.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s1">&#39;subclasses of BasePasswordHasher should provide a harden_runtime() method&#39;</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">PBKDF2PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Secure password hashing using the PBKDF2 algorithm (recommended)</span>

<span class="sd">    Configured to use PBKDF2 + HMAC + SHA256.</span>
<span class="sd">    The result is a 64 byte binary string.  Iterations may be changed</span>
<span class="sd">    safely but you must rename the algorithm if you change SHA256.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;pbkdf2_sha256&quot;</span>
    <span class="n">iterations</span> <span class="o">=</span> <span class="mi">150000</span>
    <span class="n">digest</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">password</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
        <span class="k">assert</span> <span class="n">salt</span> <span class="ow">and</span> <span class="s1">&#39;$&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">salt</span>
        <span class="n">iterations</span> <span class="o">=</span> <span class="n">iterations</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">iterations</span>
        <span class="nb">hash</span> <span class="o">=</span> <span class="n">pbkdf2</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">digest</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">digest</span><span class="p">)</span>
        <span class="nb">hash</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="nb">hash</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">$</span><span class="si">%d</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">iterations</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;iterations&#39;</span><span class="p">),</span> <span class="n">iterations</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;salt&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">)),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;hash&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
        <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">iterations</span><span class="p">)</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">iterations</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
        <span class="n">extra_iterations</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">iterations</span> <span class="o">-</span> <span class="nb">int</span><span class="p">(</span><span class="n">iterations</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">extra_iterations</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">extra_iterations</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">PBKDF2SHA1PasswordHasher</span><span class="p">(</span><span class="n">PBKDF2PasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Alternate PBKDF2 hasher which uses SHA1, the default PRF</span>
<span class="sd">    recommended by PKCS #5. This is compatible with other</span>
<span class="sd">    implementations of PBKDF2, such as openssl&#39;s</span>
<span class="sd">    PKCS5_PBKDF2_HMAC_SHA1().</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;pbkdf2_sha1&quot;</span>
    <span class="n">digest</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span>


<span class="k">class</span> <span class="nc">Argon2PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Secure password hashing using the argon2 algorithm.</span>

<span class="sd">    This is the winner of the Password Hashing Competition 2013-2015</span>
<span class="sd">    (https://password-hashing.net). It requires the argon2-cffi library which</span>
<span class="sd">    depends on native C code and might cause portability issues.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s1">&#39;argon2&#39;</span>
    <span class="n">library</span> <span class="o">=</span> <span class="s1">&#39;argon2&#39;</span>

    <span class="n">time_cost</span> <span class="o">=</span> <span class="mi">2</span>
    <span class="n">memory_cost</span> <span class="o">=</span> <span class="mi">512</span>
    <span class="n">parallelism</span> <span class="o">=</span> <span class="mi">2</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="n">argon2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">hash_secret</span><span class="p">(</span>
            <span class="n">password</span><span class="o">.</span><span class="n">encode</span><span class="p">(),</span>
            <span class="n">salt</span><span class="o">.</span><span class="n">encode</span><span class="p">(),</span>
            <span class="n">time_cost</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">time_cost</span><span class="p">,</span>
            <span class="n">memory_cost</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">memory_cost</span><span class="p">,</span>
            <span class="n">parallelism</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">parallelism</span><span class="p">,</span>
            <span class="n">hash_len</span><span class="o">=</span><span class="n">argon2</span><span class="o">.</span><span class="n">DEFAULT_HASH_LENGTH</span><span class="p">,</span>
            <span class="nb">type</span><span class="o">=</span><span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">Type</span><span class="o">.</span><span class="n">I</span><span class="p">,</span>
        <span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="o">+</span> <span class="n">data</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">argon2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">rest</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">verify_secret</span><span class="p">(</span>
                <span class="p">(</span><span class="s1">&#39;$&#39;</span> <span class="o">+</span> <span class="n">rest</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">),</span>
                <span class="n">password</span><span class="o">.</span><span class="n">encode</span><span class="p">(),</span>
                <span class="nb">type</span><span class="o">=</span><span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">Type</span><span class="o">.</span><span class="n">I</span><span class="p">,</span>
            <span class="p">)</span>
        <span class="k">except</span> <span class="n">argon2</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">VerificationError</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">False</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="p">(</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">version</span><span class="p">,</span> <span class="n">time_cost</span><span class="p">,</span> <span class="n">memory_cost</span><span class="p">,</span> <span class="n">parallelism</span><span class="p">,</span>
            <span class="n">salt</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_decode</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;variety&#39;</span><span class="p">),</span> <span class="n">variety</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;version&#39;</span><span class="p">),</span> <span class="n">version</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;memory cost&#39;</span><span class="p">),</span> <span class="n">memory_cost</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;time cost&#39;</span><span class="p">),</span> <span class="n">time_cost</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;parallelism&#39;</span><span class="p">),</span> <span class="n">parallelism</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;salt&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">)),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;hash&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">data</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="p">(</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">version</span><span class="p">,</span> <span class="n">time_cost</span><span class="p">,</span> <span class="n">memory_cost</span><span class="p">,</span> <span class="n">parallelism</span><span class="p">,</span>
            <span class="n">salt</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_decode</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="n">argon2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span>
        <span class="k">return</span> <span class="p">(</span>
            <span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">ARGON2_VERSION</span> <span class="o">!=</span> <span class="n">version</span> <span class="ow">or</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">time_cost</span> <span class="o">!=</span> <span class="n">time_cost</span> <span class="ow">or</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory_cost</span> <span class="o">!=</span> <span class="n">memory_cost</span> <span class="ow">or</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">parallelism</span> <span class="o">!=</span> <span class="n">parallelism</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="c1"># The runtime for Argon2 is too complicated to implement a sensible</span>
        <span class="c1"># hardening algorithm.</span>
        <span class="k">pass</span>

    <span class="k">def</span> <span class="nf">_decode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Split an encoded hash and return: (</span>
<span class="sd">            algorithm, variety, version, time_cost, memory_cost,</span>
<span class="sd">            parallelism, salt, data,</span>
<span class="sd">        ).</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">bits</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
            <span class="c1"># Argon2 &lt; 1.3</span>
            <span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">raw_params</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">bits</span>
            <span class="n">version</span> <span class="o">=</span> <span class="mh">0x10</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o">==</span> <span class="mi">6</span>
            <span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">raw_version</span><span class="p">,</span> <span class="n">raw_params</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">bits</span>
            <span class="k">assert</span> <span class="n">raw_version</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;v=&#39;</span><span class="p">)</span>
            <span class="n">version</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">raw_version</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="s1">&#39;v=&#39;</span><span class="p">):])</span>
        <span class="n">params</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">bit</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">raw_params</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;,&#39;</span><span class="p">))</span>
        <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">params</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span> <span class="ow">and</span> <span class="nb">all</span><span class="p">(</span><span class="n">x</span> <span class="ow">in</span> <span class="n">params</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;t&#39;</span><span class="p">,</span> <span class="s1">&#39;m&#39;</span><span class="p">,</span> <span class="s1">&#39;p&#39;</span><span class="p">))</span>
        <span class="n">time_cost</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="s1">&#39;t&#39;</span><span class="p">])</span>
        <span class="n">memory_cost</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="s1">&#39;m&#39;</span><span class="p">])</span>
        <span class="n">parallelism</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="s1">&#39;p&#39;</span><span class="p">])</span>
        <span class="k">return</span> <span class="p">(</span>
            <span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">version</span><span class="p">,</span> <span class="n">time_cost</span><span class="p">,</span> <span class="n">memory_cost</span><span class="p">,</span> <span class="n">parallelism</span><span class="p">,</span>
            <span class="n">salt</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span>
        <span class="p">)</span>


<span class="k">class</span> <span class="nc">BCryptSHA256PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Secure password hashing using the bcrypt algorithm (recommended)</span>

<span class="sd">    This is considered by many to be the most secure algorithm but you</span>
<span class="sd">    must first install the bcrypt library.  Please be warned that</span>
<span class="sd">    this library depends on native C code and might cause portability</span>
<span class="sd">    issues.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;bcrypt_sha256&quot;</span>
    <span class="n">digest</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span>
    <span class="n">library</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;bcrypt&quot;</span><span class="p">,</span> <span class="s2">&quot;bcrypt&quot;</span><span class="p">)</span>
    <span class="n">rounds</span> <span class="o">=</span> <span class="mi">12</span>

    <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">bcrypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">bcrypt</span><span class="o">.</span><span class="n">gensalt</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rounds</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="n">bcrypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span>
        <span class="n">password</span> <span class="o">=</span> <span class="n">password</span><span class="o">.</span><span class="n">encode</span><span class="p">()</span>
        <span class="c1"># Hash the password prior to using bcrypt to prevent password</span>
        <span class="c1"># truncation as described in #20138.</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">digest</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="c1"># Use binascii.hexlify() because a hex encoded bytestring is str.</span>
            <span class="n">password</span> <span class="o">=</span> <span class="n">binascii</span><span class="o">.</span><span class="n">hexlify</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">digest</span><span class="p">(</span><span class="n">password</span><span class="p">)</span><span class="o">.</span><span class="n">digest</span><span class="p">())</span>

        <span class="n">data</span> <span class="o">=</span> <span class="n">bcrypt</span><span class="o">.</span><span class="n">hashpw</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">data</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">data</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">empty</span><span class="p">,</span> <span class="n">algostr</span><span class="p">,</span> <span class="n">work_factor</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="n">salt</span><span class="p">,</span> <span class="n">checksum</span> <span class="o">=</span> <span class="n">data</span><span class="p">[:</span><span class="mi">22</span><span class="p">],</span> <span class="n">data</span><span class="p">[</span><span class="mi">22</span><span class="p">:]</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;work factor&#39;</span><span class="p">),</span> <span class="n">work_factor</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;salt&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">)),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;checksum&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">checksum</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">empty</span><span class="p">,</span> <span class="n">algostr</span><span class="p">,</span> <span class="n">rounds</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
        <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">rounds</span><span class="p">)</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rounds</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">salt</span> <span class="o">=</span> <span class="n">data</span><span class="p">[:</span><span class="mi">29</span><span class="p">]</span>  <span class="c1"># Length of the salt in bcrypt.</span>
        <span class="n">rounds</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span>
        <span class="c1"># work factor is logarithmic, adding one doubles the load.</span>
        <span class="n">diff</span> <span class="o">=</span> <span class="mi">2</span><span class="o">**</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rounds</span> <span class="o">-</span> <span class="nb">int</span><span class="p">(</span><span class="n">rounds</span><span class="p">))</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="k">while</span> <span class="n">diff</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">))</span>
            <span class="n">diff</span> <span class="o">-=</span> <span class="mi">1</span>


<span class="k">class</span> <span class="nc">BCryptPasswordHasher</span><span class="p">(</span><span class="n">BCryptSHA256PasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Secure password hashing using the bcrypt algorithm</span>

<span class="sd">    This is considered by many to be the most secure algorithm but you</span>
<span class="sd">    must first install the bcrypt library.  Please be warned that</span>
<span class="sd">    this library depends on native C code and might cause portability</span>
<span class="sd">    issues.</span>

<span class="sd">    This hasher does not first hash the password which means it is subject to</span>
<span class="sd">    bcrypt&#39;s 72 bytes password truncation. Most use cases should prefer the</span>
<span class="sd">    BCryptSHA256PasswordHasher.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;bcrypt&quot;</span>
    <span class="n">digest</span> <span class="o">=</span> <span class="kc">None</span>


<span class="k">class</span> <span class="nc">SHA1PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    The SHA1 password hashing algorithm (not recommended)</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;sha1&quot;</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">password</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
        <span class="k">assert</span> <span class="n">salt</span> <span class="ow">and</span> <span class="s1">&#39;$&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">salt</span>
        <span class="nb">hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span><span class="p">((</span><span class="n">salt</span> <span class="o">+</span> <span class="n">password</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;salt&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;hash&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">pass</span>


<span class="k">class</span> <span class="nc">MD5PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    The Salted MD5 password hashing algorithm (not recommended)</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;md5&quot;</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">password</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
        <span class="k">assert</span> <span class="n">salt</span> <span class="ow">and</span> <span class="s1">&#39;$&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">salt</span>
        <span class="nb">hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">((</span><span class="n">salt</span> <span class="o">+</span> <span class="n">password</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;salt&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;hash&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">pass</span>


<span class="k">class</span> <span class="nc">UnsaltedSHA1PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Very insecure algorithm that you should *never* use; store SHA1 hashes</span>
<span class="sd">    with an empty salt.</span>

<span class="sd">    This class is implemented because Django used to accept such password</span>
<span class="sd">    hashes. Some older Django installs still have these values lingering</span>
<span class="sd">    around so we need to handle and upgrade them properly.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;unsalted_sha1&quot;</span>

    <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s1">&#39;&#39;</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">salt</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span>
        <span class="nb">hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span><span class="p">(</span><span class="n">password</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
        <span class="k">return</span> <span class="s1">&#39;sha1$$</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="nb">hash</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;sha1$$&#39;</span><span class="p">)</span>
        <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="p">[</span><span class="mi">6</span><span class="p">:]</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;hash&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">pass</span>


<span class="k">class</span> <span class="nc">UnsaltedMD5PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Incredibly insecure algorithm that you should *never* use; stores unsalted</span>
<span class="sd">    MD5 hashes without the algorithm prefix, also accepts MD5 hashes with an</span>
<span class="sd">    empty salt.</span>

<span class="sd">    This class is implemented because Django used to store passwords this way</span>
<span class="sd">    and to accept such password hashes. Some older Django installs still have</span>
<span class="sd">    these values lingering around so we need to handle and upgrade them</span>
<span class="sd">    properly.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;unsalted_md5&quot;</span>

    <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s1">&#39;&#39;</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">salt</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span>
        <span class="k">return</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">password</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">37</span> <span class="ow">and</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;md5$$&#39;</span><span class="p">):</span>
            <span class="n">encoded</span> <span class="o">=</span> <span class="n">encoded</span><span class="p">[</span><span class="mi">5</span><span class="p">:]</span>
        <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;hash&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">3</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">pass</span>


<span class="k">class</span> <span class="nc">CryptPasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Password hashing using UNIX crypt (not recommended)</span>

<span class="sd">    The crypt module is not supported on all platforms.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">&quot;crypt&quot;</span>
    <span class="n">library</span> <span class="o">=</span> <span class="s2">&quot;crypt&quot;</span>

    <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">get_random_string</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span>
        <span class="n">crypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span>
        <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">salt</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">crypt</span><span class="o">.</span><span class="n">crypt</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">data</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>  <span class="c1"># A platform like OpenBSD with a dummy crypt module.</span>
        <span class="c1"># we don&#39;t need to store the salt, but Django used to do this</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">crypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">crypt</span><span class="o">.</span><span class="n">crypt</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">data</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;$&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span>
        <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;algorithm&#39;</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;salt&#39;</span><span class="p">),</span> <span class="n">salt</span><span class="p">),</span>
            <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;hash&#39;</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">3</span><span class="p">)),</span>
        <span class="p">])</span>

    <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span>
        <span class="k">pass</span>
</pre></div>

          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">Mar 04, 2020</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    <a href="../../../index.html" title="Module code" accesskey="U">up</a></div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>